using System;
namespace HB.Expand
{
    /// <summary>
    /// 时间类型拓展
    /// </summary>
    public static class DateTimeFormat
    {

        static DateTime DT = new DateTime(1970, 1, 1);
        /// <summary>
        /// 转换为时间戳，以秒为单位
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ToTimeStamp(this DateTime time)
        {
            return (long)(time.ToUniversalTime() - DT).TotalSeconds;
        }
        /// <summary>
        /// 转换为时间戳，以毫秒为单位
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ToTimeStampMs(this DateTime time)
        {
            return (long)(time.ToUniversalTime() - DT).TotalMilliseconds;
        }
        /// <summary>
        /// 当天00:00:00的时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ToTimeStampOfDayStart(this DateTime time)
        {
            DateTime dd = new DateTime(time.Year, time.Month, time.Day, 0, 0, 0);
            return dd.ToTimeStamp();
        }
        /// <summary>
        /// 当月1号00:00：00的时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static long ToTimeStampOfMonthStart(this DateTime time)
        {
            DateTime dd = new DateTime(time.Year, time.Month, 1, 0, 0, 0);
            return dd.ToTimeStamp();
        }
        /// <summary>
        /// 从时间戳（秒）转为DataTime
        /// </summary>
        /// <param name="second"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromSecond(this long second)
        {
            return DT.AddSeconds(second).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（秒）转为DataTime
        /// </summary>
        /// <param name="second"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromSecond(this int second)
        {
            return DT.AddSeconds(second).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（秒）转为DataTime
        /// </summary>
        /// <param name="second"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromSecond(this double second)
        {
            return DT.AddSeconds(second).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（秒）转为DataTime
        /// </summary>
        /// <param name="second"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromSecond(this float second)
        {
            return DT.AddSeconds(second).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（毫秒）转为DataTime
        /// </summary>
        /// <param name="milliSecond"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromMilliSecond(this long milliSecond)
        {
            return DT.AddMilliseconds(milliSecond).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（毫秒）转为DataTime
        /// </summary>
        /// <param name="milliSecond"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromMilliSecond(this int milliSecond)
        {
            return DT.AddMilliseconds(milliSecond).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（毫秒）转为DataTime
        /// </summary>
        /// <param name="milliSecond"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromMilliSecond(this float milliSecond)
        {
            return DT.AddMilliseconds(milliSecond).ToLocalTime();
        }
        /// <summary>
        /// 从时间戳（毫秒）转为DataTime
        /// </summary>
        /// <param name="milliSecond"></param>
        /// <returns></returns>
        public static DateTime ToDateTimeFromMilliSecond(this double milliSecond)
        {
            return DT.AddMilliseconds(milliSecond).ToLocalTime();
        }
        /// <summary>
        /// yyyy/MM/dd HH:mm:ss
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ToString_yyyyMMddHHmmss(this DateTime time)
        {
            return time.ToString("yyyy/MM/dd HH:mm:ss");
        }
        /// <summary>
        /// yyyyMMdd
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ToString_yyyyMMdd(this DateTime time)
        {
            return time.ToString("yyyyMMdd");
        }
        /// <summary>
        /// 生成yyyyMMdd数值
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static int ToInt_yyyyMMdd(this DateTime time)
        {
            return time.Year * 10000 + time.Month * 100 + time.Day;
        }
        /// <summary>
        /// yyyy/MM/dd HH:mm:ss.ffffff
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static string ToString_yyyyMMddHHmmssffffff(this DateTime time)
        {
            return time.ToString("yyyy/MM/dd HH:mm:ss.ffffff");
        }
        /// <summary>
        /// 本年度第几周
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static WeekInYear WeekOfYear(this DateTime time)
        {
            System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
            int weekOfYear = gc.GetWeekOfYear(time, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday);
            return new WeekInYear() { WeekIndex = weekOfYear, Year = time.Year };
        }
        /// <summary>
        /// 本年度第几季度
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static int QuarterOfYear(this DateTime time)
        {
            return (time.Month - 1) / 3 + 1;
        }
        /// <summary>
        /// 获取所属周开始和结束日期
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static TimeRange GetRangeOfBelongWeek(this DateTime time)
        {
            int offset = (int)time.DayOfWeek;
            if (offset == 0) { offset = 7; }
            var start = time.AddDays(1 - offset);
            var end = time.AddDays(7 - offset);
            return new TimeRange(new DateTime(start.Year, start.Month, start.Day, 0, 0, 0), new DateTime(end.Year, end.Month, end.Day, 23, 59, 59));
        }
        /// <summary>
        /// 获取所属月开始和结束日期
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static TimeRange GetRangeOfBelongMonth(this DateTime time)
        {
            System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
            int count = gc.GetDaysInMonth(time.Year, time.Month);
            return new TimeRange(new DateTime(time.Year, time.Month, 1, 0, 0, 0), new DateTime(time.Year, time.Month, count, 23, 59, 59));
        }
        /// <summary>
        /// 获取所属季度开始和结束日期
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static TimeRange GetRangeOfBelongQuarter(this DateTime time)
        {
            var quarter = time.QuarterOfYear();
            int startmonth = (quarter - 1) * 3 + 1;
            int endmonth = quarter * 3;
            System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
            int count = gc.GetDaysInMonth(time.Year, endmonth);
            return new TimeRange(new DateTime(time.Year, startmonth, 1, 0, 0, 0), new DateTime(time.Year, quarter * 3, count, 23, 59, 59));
        }
        /// <summary>
        /// 获取所属年开始和结束日期
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static TimeRange GetRangeOfBelongYear(this DateTime time)
        {
            System.Globalization.GregorianCalendar gc = new System.Globalization.GregorianCalendar();
            int count = gc.GetDaysInMonth(time.Year, 12);
            return new TimeRange(new DateTime(time.Year, 1, 1, 0, 0, 0), new DateTime(time.Year, 12, count, 23, 59, 59));
        }
        /// <summary>
        /// 计算指定日期与现在的时间间隔（可用于计算年龄）
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static TimeInterval GetIntervalFromNow(this DateTime time)
        {
            var now = DateTime.Now;
            var rangeYear = now.Year - time.Year;
            var rangeMonth = now.Month - time.Month;
            var rangeDay = now.Day - time.Day;
            if (rangeDay < 0) { rangeMonth -= 1; rangeDay += 30; }
            if (rangeMonth < 0) { rangeYear -= 1; rangeMonth += 12; }
            return new TimeInterval() { Year = rangeYear, Month = rangeMonth, Day = rangeDay };
        }
    }
}
